#include "yuvrecordthread.h"
#include <QFile>

extern "C" {

    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libavutil/avutil.h>
    #include <libavutil/imgutils.h>
}


#define ERRMSG(num) char errBuf[1024]; \
    av_strerror(num,errBuf,sizeof(errBuf))


YUVRecordThread::YUVRecordThread(QObject *parent) : QThread(parent)
{

    connect(this,&QThread::finished,this,&QThread::deleteLater);
}

YUVRecordThread::~YUVRecordThread()
{

    disconnect();

    // 终止正在运行的run方法
    requestInterruption();

    quit();

    wait();

    qDebug() << "YUVRecordThread destory";
}

void YUVRecordThread::run()
{


    const char* fmt = "avfoundation";

    AVInputFormat* inputFmt = av_find_input_format(fmt);

    if(inputFmt == nullptr) {

        qDebug() << "av_find_input_format not find " << fmt;
        return;
    }

    AVFormatContext* fmtContext = nullptr;
    const char* url = "0";

    AVDictionary* dict = nullptr;

    av_dict_set(&dict,"framerate","30",0);
    // 2 * 1280* 720 = 1843200
    av_dict_set(&dict,"pixel_format","yuyv422",0);
    av_dict_set(&dict,"video_size","1280x720",0);

    int res =  avformat_open_input(&fmtContext,url,inputFmt,&dict);

    if(res != 0) {

        ERRMSG(res);
        qDebug() << "avformat_open_input fail " << errBuf;
        return;
    }

    AVCodecParameters* parameters = fmtContext->streams[0]->codecpar;

    int imageSize = av_image_get_buffer_size((AVPixelFormat)parameters->format,parameters->width,parameters->height,1);

//    av_get_pix_fmt_name((AVPixelFormat)parameters->format);
    ;

    int fmtBytes = av_get_bits_per_pixel(av_pix_fmt_desc_get((AVPixelFormat)parameters->format)) >> 3;

    qDebug()  << "fmtBytes:" << fmtBytes << " width:" << parameters->width  << " height:" << parameters->height;
    qDebug() << "imageSize:" << imageSize;

    AVPacket* packet = av_packet_alloc();

    if(packet == nullptr) {


        avformat_close_input(&fmtContext);
        qDebug() << "av_packet_alloc fail";

        return;
    }


    const char* video_save_path = "/Users/tgy/Documents/ffmpeg/video/yuv_record_01.yuv";

    QFile outFile(video_save_path);

    if(!outFile.open(QFile::WriteOnly)) {

        av_packet_free(&packet);
        avformat_close_input(&fmtContext);
        qDebug() << "open " << video_save_path << " fail";
        return;
    }



    while (!isInterruptionRequested()) {

        res = av_read_frame(fmtContext,packet);

        if(res == 0) {

            outFile.write((char*)packet->data,packet->size);
            qDebug() << "size:" << packet->size;
            av_packet_unref(packet);

        }else if(res == AVERROR(EAGAIN)) {

            continue;
        }else {

            ERRMSG(res);
            qDebug() << "av_read_frame fail " << errBuf;
            break;
        }

    }

    outFile.close();
    av_packet_free(&packet);
    avformat_close_input(&fmtContext);

}


